package com.aizuda.service.autoconfigure;

import com.aizuda.service.editors.DoubleEditor;
import com.aizuda.service.editors.IntegerEditor;
import com.aizuda.service.editors.LongEditor;
import com.aizuda.service.handler.ConditionalToStringSerializer;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.nio.charset.StandardCharsets;
import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author hjw
 * @description
 * @date 2025年06月26日 10:39
 */
@Lazy
@RestControllerAdvice
@Configuration(
        proxyBeanMethods = false
)
public class JsonAutoConfiguration {
    @Value("${spring.jackson.time-zone}")
    private String timeZone = "UTC+8";

    public JsonAutoConfiguration() {
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(Date.class, new CustomDateEditor(new DateFormat() {
            private final List<? extends DateFormat> DATE_FORMATS = Arrays.asList(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), new SimpleDateFormat("yyyy-MM-dd HH:mm"), new SimpleDateFormat("yyyy-MM-dd"), new SimpleDateFormat("yyyy-MM"));

            public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
                throw new UnsupportedOperationException("This custom date formatter can only be used to *parse* Dates.");
            }

            public Date parse(String source, ParsePosition pos) {
                Iterator var3 = this.DATE_FORMATS.iterator();

                Date date;
                do {
                    if (!var3.hasNext()) {
                        return null;
                    }

                    DateFormat dateFormat = (DateFormat) var3.next();
                    date = dateFormat.parse(source, pos);
                } while (null == date);

                return date;
            }
        }, true));
        binder.registerCustomEditor(Long.class, new LongEditor());
        binder.registerCustomEditor(Double.class, new DoubleEditor());
        binder.registerCustomEditor(Integer.class, new IntegerEditor());
    }

    @Bean
    public HttpMessageConverters jacksonHttpMessageConverters() {
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        builder.serializationInclusion(JsonInclude.Include.NON_NULL);
        builder.featuresToEnable(new Object[]{MapperFeature.PROPAGATE_TRANSIENT_MARKER});
        ObjectMapper objectMapper = builder.build();
        SimpleModule simpleModule = new SimpleModule();
        simpleModule.addSerializer(Long.class, new ConditionalToStringSerializer());
        objectMapper.registerModule(simpleModule);
        objectMapper.setTimeZone(TimeZone.getTimeZone(this.timeZone));
        MappingJackson2HttpMessageConverter jacksonConverter = new MappingJackson2HttpMessageConverter(objectMapper);
        jacksonConverter.setDefaultCharset(StandardCharsets.UTF_8);
        StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(StandardCharsets.UTF_8);
        stringConverter.setDefaultCharset(StandardCharsets.UTF_8);
        return new HttpMessageConverters(new HttpMessageConverter[]{jacksonConverter, stringConverter});
    }
}
